package pogvue.gui.hub;

import pogvue.io.AlignFile;
import pogvue.io.FastaFile;
import pogvue.io.FileParse;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.MalformedURLException;
import pogvue.io.*;
import pogvue.gui.*;
import javax.swing.*;
import java.awt.*;
import java.util.*;

import pogvue.gui.menus.*;
import pogvue.datamodel.*;


/**
 * Created by IntelliJ IDEA.
 * User: mclamp
 * Date: Aug 11, 2007
 * Time: 4:55:46 PM
 * To change this template use File | Settings | File Templates.
 */
public class GenomeInfoFactory {
//  public static final String urlstub        = "http://www.broad.mit.edu/~mclamp/alpheus/";
//  public static final String fastaurlstub   = "http://www.broad.mit.edu/~mclamp/";
  //public static final String urlstub        = "http://srv/~mclamp/";
  public static final String urlstub        = "http://localhost:8080/~mclamp/";
  public static final String fastaurlstub   = AlignViewport.getFastaURL();

  public static final String geneidstub     = "getGenesById.php?";
  public static final String chromosomestub = "queryChromosomes.php";
  public static final String regionstub     = "fetchmam.php?";
  public static final String graphstub      = "fetchmamgraph.php?";
  public static final String humanstub      = "fetchhuman.php?";
  public static final String featurestub    = "fetchmamgff.php?";
  public static final String genestub       = "fetchgene.php?";
  public static final String repeatstub     = "fetchrepeat.php?";
  public static final String mrnastub       = "fetch_mrna.php?";
  public static final String geneinfostub   = "fetch_geneinfo.php?";

  public static BufferedReader getGenesById(String idstr) throws IOException {
    String query = urlstub + geneidstub + "search_str=" + idstr;
    
    FileParse fp = new FileParse(query,"URL");
    
    return fp.getBufferedReader();
  }
  public static GappedFastaFile getRegion(String chr,int start, int end) throws IOException {
    String regionStr = "query=" + chr + "&start=" + start + "&end=" + end + "&z=2";

    return getRegion(regionStr);
  }
  public static GappedFastaFile getRegion(String regionStr) throws IOException{
    String query    = AlignViewport.getFastaURL() + regionStr;

    System.out.println("Getting region " + query);

    GappedFastaFile fp = new GappedFastaFile(query,"URL",false);
    
    return fp;
  }
  public static FastaFile getHumanRegion(String regionStr) throws IOException{
    String query    = fastaurlstub + regionStr;
    System.out.println("Query " + query);
    FastaFile fp = new FastaFile(query,"URL",false);
    
    return fp;
  }

    public static BlatFile getBlatFile(String regstr) throws IOException {

	System.out.println("Query is " + AlignViewport.getBLTURL()   + regstr);

	String blt_url   = AlignViewport.getBLTURL()   + regstr;

	BlatFile blt   = new BlatFile(blt_url,"URL");
	    
	return blt;
    }
	
   public static GappedFastaFile getGappedFastaFile(String fileStr) throws IOException{
    GappedFastaFile fp = new GappedFastaFile(fileStr,"File",false);
    
    return fp;
  }
  public static FastaFile getFastaFile(String fileStr) throws IOException{
    FastaFile fp = new FastaFile(fileStr,"File",false);
    
    return fp;
  }
    public static GraphFile  getRegionGraph(String regionStr) throws IOException {
      String query = AlignViewport.getGRFURL()  + regionStr;

      System.out.println("Query string " + query);
    GraphFile grf  = new GraphFile(query,"URL",false);

    return grf;

  }
  public static GFFFile  getRegionFeatures(String regionStr) throws IOException {
    String query = AlignViewport.getGFFURL() + regionStr;


    System.out.println("Query string " + query);

    GFFFile gff  = new GFFFile(query,"URL",false);

    return gff;

  }
  public static GFFFile getRegionGenes(String regionStr) throws IOException {
    String query = AlignViewport.getGFFURL() + regionStr;
      
      GFFFile gff = new GFFFile(query,"URL",false);
      
      return gff;
  }
  public static GFFFile getRegionRepeats(String regionStr) throws IOException {
    String query = AlignViewport.getGFFURL() + regionStr;
      
      GFFFile gff = new GFFFile(query,"URL",false);
      
      return gff;
  }

  public static BlatFile getRegionMrna(String regionStr) throws IOException {
    String query = AlignViewport.getBLTURL() + regionStr;
      
    BlatFile gff = new BlatFile(query,"URL",false);
      
      return gff;
  }

  
  public static GFFFile  getGraphFeatures(String regionStr) throws IOException {
    String query = AlignViewport.getGRFURL()+ regionStr;
    System.out.println("******* Graph query " + query);

    GFFFile gff  = new GFFFile(query,"URL",false);

    return gff;

  }

  // getChromosomes
  public static BufferedReader getChromosomes() throws IOException {
    String query = urlstub + chromosomestub;
    
    FileParse fp = new FileParse(query,"URL");
    
    return fp.getBufferedReader();
  }
	
    public static GeneInfoFile getGeneInfo(String chr, int start, int end) {
	String regionStr = "query=" + chr + "&start=" + start + "&end=" + end + "&types=name";
	
        String query = AlignViewport.getInfoURL() + regionStr;
	try {
	    
	    GeneInfoFile gif = new GeneInfoFile(query,"URL",false);
	    
	    return gif;
	} catch (IOException e) {
	    System.out.println("ERROR reading GeneInfoFile " + query);
            e.printStackTrace();
	}
	return null;
    }
  public static AlignSplitPanel makePanel(AlignmentI al, String title,double width1, double width2, GFFFragment gff,int offset, int start, int end, int width) {
    
	AlignSplitPanel asp = new AlignSplitPanel(al,title,width1,width2,gff);

	AlignmentPanel ap1 = asp.getAlignmentPanel1();
	AlignmentPanel ap2 = asp.getAlignmentPanel2();
	
	AlignViewport  av1 = ap1.getAlignViewport();
	AlignViewport  av2 = ap2.getAlignViewport();
	
	
	av1.setOffset(offset);
	av2.setOffset(offset);
		
	int startres = (int)((end-start)/2 - (width)/av1.getCharWidth());

	av1.setStartRes(startres);
	startres = (int)((end-start)/2 - (width)/av2.getCharWidth());

	av2.setStartRes(startres);
	
	
	return asp;
	
  }
  public static JPanel makeSinglePanel(AlignmentI al, String title,double width1, GFFFragment gff) {
    JPanel     jp = new JPanel(new BorderLayout());
	
    AlignViewport  av         = new AlignViewport(al,false,true,true,false);
    Controller     controller = new Controller();

    av.setController(controller);

    
    for (int i = 0; i < al.getHeight(); i++) {
      if (al.getSequenceAt(i) instanceof SequenceFragment){
	
	((SequenceFragment)al.getSequenceAt(i)).setAlignViewport(av);
      }
      if (al.getSequenceAt(i) instanceof GFFFragment ) {
	
	((GFFFragment)al.getSequenceAt(i)).setAlignViewport(av);
      }
    }

    AlignmentPanel ap         = new AlignmentPanel(av,controller);
        
    av.setRenderer(new GraphRenderer());
    av.setFont(new Font("Helvetica",Font.PLAIN,0));
    av.setCharWidth(width1,"AlignmentPanel");
    av.setPIDBaseline(70);
    av.setCharHeight(10);
    
    //MenuManager m = new MenuManager(jp, av, controller);  
	
    ap.setMinimumSize(new Dimension(0,0));
	
	
    // This is needed when the panel is brought up from a Choosepanel button.
    ap.repaint();
	
    jp.add("Center",ap);
    return jp;
  }

    public static Hashtable getGenes(String chr, int start, int end) {
	GeneInfoFile gif = GenomeInfoFactory.getGeneInfo(chr,start,end);
		
	gif.parse();
		
	Hashtable gene = gif.getGeneHash();
		
	Enumeration en3 = gene.keys();
		
	while (en3.hasMoreElements()) {
	    String genename = (String)en3.nextElement();
	    
	    System.out.print(genename);
	    
	    Hashtable geneh = (Hashtable)gene.get(genename);
	    
	    if (geneh.containsKey("name")) {
		Vector vals = (Vector)geneh.get("name");
		System.out.print("\tName\t" + geneh.get("name"));
	    }
	    if (geneh.containsKey("pfam")) {
		Vector vals = (Vector)geneh.get("pfam");
		System.out.print("\tPfam\t" + geneh.get("pfam"));
	    }
	    if (geneh.containsKey("class")) {
		Vector vals = (Vector)geneh.get("class");
		System.out.print("\tClass\t" + geneh.get("class"));
	    }
	    if (geneh.containsKey("desc")) {
		Vector vals = (Vector)geneh.get("desc");
		System.out.print("\tDesc\t" + geneh.get("desc"));
	    }
	    System.out.println();
	    System.out.println();
	}
	
	return gene;
    }

    public static Alignment requestRegion(String chr, int start, int end,Vector feat) {

	// Hash the input features by type   - farm out
	
      LinkedHashMap typeorder = AlignViewport.readGFFConfig("http://www.broad.mit.edu/~mclamp/pogvue/gff.conf","URL");
      Vector        inputFeat = GFF.hashFeatures(feat,start,typeorder,true);


      // This is the generic regions string for querying the website
      
      String regstr = "query=" + chr + "&start=" + start + "&end=" + end + "&z=2";
      
      
      Alignment al = Alignment.getDummyAlignment("Human",chr,start,end);
      
      // Now add in the features
      
      al.addSequences(inputFeat);
      
      try {
	
	// Hashtable genes = GenomeInfoFactory.getGenes(chr,start,end);
	
	// Now the GFF features
	    
	System.out.println("Getting gff");
	
	GFFFile   gff = GenomeInfoFactory.getRegionFeatures(regstr);
	GraphFile grf = GenomeInfoFactory.getRegionGraph(regstr);
	BlatFile  blt = GenomeInfoFactory.getBlatFile(regstr);
	
	System.out.println("Parsing gff");
	gff.parse();	    
	
	System.out.println("Parsing graph");
	grf.parse();
	
	System.out.println("Parsing blat");
	blt.parse();
	
	
	// Group into features and subfeatures by hitname
	Vector  tmpgenefeat = GFFFile.extractFeatures(gff.getFeatures(),"gene");
	
	Vector  tmpfeat     = GFFFile.groupFeatures(gff.getFeatures(),true);
	
	System.out.println("Tmp feat " + tmpgenefeat.size());
	
	
	
	// find the 'proper' gene name for each gene
	
	//GenomeInfoFactory.assignNames(genes,tmpgenefeat);
	tmpgenefeat = GFFFile.groupFeatures(tmpgenefeat,true);
	
	System.out.println("Tmp feat" + tmpgenefeat.size());
	System.out.println("Hashing gff");
	
	Vector  geneFeat = GFF.hashFeatures(tmpgenefeat,0,typeorder,true);
	Vector  gffFeat =  GFF.hashFeatures(tmpfeat,0,typeorder,false);	
	
	System.out.println("Hashing grf");
	
	Vector  grfFeat = GFF.hashFeatures(grf.getFeatures(),0,typeorder,false);
	
	System.out.println("Hashing blat "  + blt.getFeatures().size());
	
	Vector  bltFeat = GFF.hashFeatures(blt.getFeatures(),0,typeorder,true);
	
	System.out.println("Adding genes "  + geneFeat.size());
	al.addSequences(geneFeat,1);
	
	System.out.println("Adding gff "  + gffFeat.size());
	al.addSequences(gffFeat);
	
	System.out.println("Adding graph "  + grfFeat.size());
	al.addSequences(grfFeat,3);
	
	System.out.println("Adding blat "  + bltFeat.size());
	al.addSequences(bltFeat);
	
      } catch (IOException e) {
	e.printStackTrace();
      }
      return al;
    }

  public static void assignNames(Hashtable genes, Vector feat) {
    for (int i = 0;i  < feat.size(); i++) {

      SequenceFeature tmpsf = (SequenceFeature)feat.elementAt(i);

      if (tmpsf.getFeatures() != null) {

	Vector tmpsf2 = (Vector)tmpsf.getFeatures();

	for (int j = 0; j < tmpsf2.size(); j++) {
	  SequenceFeature sf = (SequenceFeature)tmpsf2.elementAt(j);

	  String id = sf.getHitFeature().getId();
	  String name = null;

	  Enumeration en = genes.keys();

	  while (en.hasMoreElements()) {
	    String ensg = (String)en.nextElement();

	    if (id.indexOf(ensg) == 0) {
	      Hashtable geneh = (Hashtable)genes.get(ensg);
	  
	      if (geneh.containsKey("name")) {
		Vector vals = (Vector)geneh.get("name");
		name = (String)vals.elementAt(0);
	      }
	    }
	  }
	  
	  if (sf.getHitFeature() != null && name != null) {
	      System.out.println("Setting name for " + sf.getHitFeature().getId() +  " to " + name);
	    sf.getHitFeature().setId(name);
	  }
	}
      }
    }
  }
}
